package com.balance.anole.client.retail.view;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.ActionSetSeparator;
import org.eclipse.ui.part.ViewPart;

import com.balance.anole.admin.to.AgentTO;
import com.balance.anole.admin.to.StaffInfoTO;
import com.balance.anole.business.to.BusinessDateTO;
import com.balance.anole.business.to.ProductItemTO;
import com.balance.anole.business.to.ProductPriceTO;
import com.balance.anole.business.to.ShopPaymentTO;
import com.balance.anole.business.to.ShopReceiptPdtItemTO;
import com.balance.anole.business.to.ShopReceiptTO;
import com.balance.anole.client.common.service.CommonService;
import com.balance.anole.client.retail.dialog.RetailAssemCloseDialog;
import com.balance.anole.client.retail.dialog.RetailCloseDialog;
import com.balance.anole.client.retail.dialog.RetailHoldSelectDialog;
import com.balance.anole.client.retail.payment.PaymentHelper;
import com.balance.anole.client.retail.provider.RetailLabelProvider;
import com.balance.anole.client.retail.service.RetailService;
import com.balance.anole.client.retail.service.exception.RetailServiceException;
import com.balance.anole.client.retail.vo.RetailReceiptPrintVO;
import com.balance.anole.client.retail.vo.RetailVO;
import com.balance.anole.client.retail.vo.RetailReceiptPrintVO.PaymentItemDetail;
import com.balance.anole.client.retail.vo.RetailReceiptPrintVO.ProductItemDetail;
import com.balance.anole.common.to.CodeLookTO;
import com.balance.anole.erp.common.dialog.ProductSelector2;
import com.balance.anole.erp.common.model.ProductItemVO;
import com.balance.anole.erp.common.provider.StaffComboLabelProvider;
import com.balance.anole.erp.common.service.BizCodesService;
import com.balance.anole.erp.component.TextClock;
import com.balance.anole.erp.security.SessionManager;
import com.balance.anole.erp.util.Messages;
import com.balance.anole.erp.util.NumberUtil;
import com.balance.anole.erp.util.SWTResourceManager;
import com.balance.anole.erp.util.ServicesCenter;
import com.balance.anole.utils.Constants;
import com.balance.anole.utils.DateUtil;
import com.balance.anole.utils.FormatHelper;

@SuppressWarnings("restriction")
public class RetailView extends ViewPart{
	public RetailView() {
	}

	public static final String ID = RetailView.class.getName();

	public static final String CODE_PROCESS = "PROGRESS";
	public static final String CODE_PROGRESS_HOLD = "H";
	public static final String CODE_PROGRESS_FINAL = "F";
	public static final String CODE_PROGRESS_CANCEL = "C";

	private ShopReceiptTO shopReceiptTO;
	private RetailVO selectRetailVO;
	private Label label_statusData;

	private boolean isRejected = false;
	private boolean printReceipt = true;

	private final CommonService cs = ServicesCenter.getServicesCenter().getService(CommonService.class);
	private final RetailService rs = ServicesCenter.getServicesCenter().getService(RetailService.class);
	private final IContextService contextService = (IContextService) PlatformUI.getWorkbench().getService(IContextService.class);
	private final IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);

	private List<IHandlerActivation> activatedHandlers = new ArrayList<IHandlerActivation>();

	@Override
	public void createPartControl(final Composite parent) {

		contextService.activateContext("com.balance.anole.client.retail.view.RetailView");
		activatedHandlers.clear();

		final BusinessDateTO businessDate = cs.getBusinessDate();

		if(businessDate == null){
			MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "交易日不存在！");
			return;
		}

		final List<RetailVO> l_Retail = new ArrayList<RetailVO>();
		final Set<ShopReceiptPdtItemTO> receipt_ProdItem = new HashSet<ShopReceiptPdtItemTO>();

		FormData formData;
		Composite container = new Composite(parent, SWT.NONE);
		container.setLayout(new FormLayout());

		//-----------------------Line 1 start-------------------------------------------
		Label label_shop = new Label(container,SWT.LEFT);
		label_shop.setText("门店：");
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(0,10);
		label_shop.setLayoutData(formData);

		Label label_shopData = new Label(container,SWT.LEFT);
		StaffInfoTO loginUser = SessionManager.getInstance().getLoginUser().getStaffInfo();
		final AgentTO staffOwner = loginUser.getStaffOwner();
		String agentName = "请检查登录用户所属门店！";
		if(staffOwner != null){
			agentName = staffOwner.getAgentName();
		}else {
			label_shopData.setBackground(SWTResourceManager.getColor(SWT.COLOR_RED));
		}
		label_shopData.setText("[" + agentName + "]");
		formData = new FormData();
		formData.left = new FormAttachment(label_shop,2);
		formData.top = new FormAttachment(0,10);
		label_shopData.setLayoutData(formData);

		Label label_lineNo = new Label(container,SWT.LEFT);
		label_lineNo.setText("柜号：");
		formData = new FormData();
		formData.left = new FormAttachment(label_shopData,15);
		formData.top = new FormAttachment(0,10);
		label_lineNo.setLayoutData(formData);

		Label label_lineNoData = new Label(container,SWT.LEFT);
		label_lineNoData.setText("[01]");
		formData = new FormData();
		formData.left = new FormAttachment(label_lineNo,2);
		formData.top = new FormAttachment(0,10);
		label_lineNoData.setLayoutData(formData);

		final TextClock textClock = new TextClock(container, SWT.LEFT);
		formData = new FormData();
		formData.right = new FormAttachment(100, -5);
		formData.top = new FormAttachment(0,10);
		formData.width = 150;
		formData.height = 20;
		textClock.setLayoutData(formData);

		Label label_businessDate = new Label(container,SWT.LEFT);
		label_businessDate.setText("业务日期：");
		formData = new FormData();
		formData.right = new FormAttachment(textClock,-5);
		formData.top = new FormAttachment(0,10);
		label_businessDate.setLayoutData(formData);
		//-----------------------Line 1 end-------------------------------------------

		//-----------------------Line 2 start-----------------------------------------
		Label label_cashier;
		label_cashier = new Label(container,SWT.LEFT);
		label_cashier.setText("收银员：");
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(label_shop,15);
		label_cashier.setLayoutData(formData);

		Label label_cashierData = new Label(container,SWT.RIGHT);
		label_cashierData.setText("[" + loginUser.getStaffName() +"]");
		formData = new FormData();
		formData.left = new FormAttachment(label_cashier,5);
		formData.top = new FormAttachment(label_shop,15);
		label_cashierData.setLayoutData(formData);

		Label label_status = new Label(container,SWT.LEFT);
		label_status.setText("状态：");
		formData = new FormData();
		formData.left = new FormAttachment(label_shopData,15);
		formData.top = new FormAttachment(label_shop,15);
		label_status.setLayoutData(formData);

		label_statusData = new Label(container,SWT.NONE);

		/*if(isRejected){
			label_statusData.setText("[退货]");
			label_statusData.setForeground(SWTResourceManager.getColor(255, 0, 0));
		}else{
			label_statusData.setText("[正常销售]");
			label_statusData.setForeground(SWTResourceManager.getColor(0, 0, 0));
		}*/

		//default should be 正常销售
		label_statusData.setText("[正常销售] [打印]");
		label_statusData.setForeground(SWTResourceManager.getColor(0, 0, 0));

		formData = new FormData();
		formData.left = new FormAttachment(label_status,5);
		formData.top = new FormAttachment(label_shop,15);
		label_statusData.setLayoutData(formData);
		//-----------------------Line 2 end-----------------------------------------

		//-----------------------Line 3 start---------------------------------------
		final TableViewer tableViewer = new TableViewer(container, SWT.BORDER|SWT.FULL_SELECTION);
		final Table productItemtable;
		productItemtable = tableViewer.getTable();
		formData.right = new FormAttachment(productItemtable, 0, SWT.RIGHT);
		productItemtable.setLinesVisible(true);
		productItemtable.setHeaderVisible(true);
		formData = new FormData();
		formData.top = new FormAttachment(label_cashier,20);
		formData.bottom = new FormAttachment(65,-50);
		formData.left =  new FormAttachment(0,15);
		formData.right =  new FormAttachment(100,-15);
		productItemtable.setLayoutData(formData);

		String[] columnNames = new String[]{"商品编号",
				"商品名称",
				"颜色",
				"规格",
				"单价",
				"折率",
				"数量",
				"金额"};

		int[] columnWidths = new int[]{90,120,60,60,80,50,50,80};
		int[] columnAlignments = new int[]{SWT.CENTER,SWT.CENTER,SWT.CENTER,SWT.CENTER,SWT.CENTER,SWT.CENTER,SWT.CENTER,SWT.CENTER};

		for(int i=0;i<columnNames.length;i++){
			TableColumn tableColumn = new TableColumn(productItemtable,columnAlignments[i]);
			tableColumn.setText(columnNames[i]);
			tableColumn.setWidth(columnWidths[i]);
		}

		final WritableList wl = new WritableList(l_Retail,RetailVO.class);
		ObservableListContentProvider opContentProvider = new ObservableListContentProvider();
		tableViewer.setContentProvider(opContentProvider);
		tableViewer.setLabelProvider(new RetailLabelProvider());
		tableViewer.setInput(wl);


		//-----------------------Line 3 end-----------------------------------------

		//-----------------------Line 4 start-----------------------------------------
		Group groupLeft = new Group(container, SWT.NULL);
		groupLeft.setText("交易信息");
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(productItemtable,25);
		formData.bottom = new FormAttachment(100,-125);
		formData.right = new FormAttachment(50,-15);
		groupLeft.setLayoutData(formData);
		groupLeft.setLayout(new FormLayout());

		Label label_totalNumSold = new Label(groupLeft,SWT.RIGHT);
		label_totalNumSold.setText("总数量:");
		label_totalNumSold.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(0,15);
		label_totalNumSold.setLayoutData(formData);

		final Label label_totalNumSoldData = new Label(groupLeft,SWT.RIGHT);
		label_totalNumSoldData.setText("0");
		label_totalNumSoldData.setFont(SWTResourceManager.getFont("", 16, SWT.BOLD));
		formData = new FormData();
		formData.left = new FormAttachment(label_totalNumSold,5);
		formData.top = new FormAttachment(0,15);
		formData.right = new FormAttachment(100,-35);
		label_totalNumSoldData.setLayoutData(formData);

		Label label_prepaidValue = new Label(groupLeft,SWT.RIGHT);
		label_prepaidValue.setText("折前金额:");
		label_prepaidValue.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(label_totalNumSold,10);
		label_prepaidValue.setLayoutData(formData);

		final Label label_prepaidValueData = new Label(groupLeft,SWT.RIGHT);
		label_prepaidValueData.setText("0.00");
		label_prepaidValueData.setFont(SWTResourceManager.getFont("", 16, SWT.BOLD));
		formData = new FormData();
		formData.left = new FormAttachment(label_prepaidValue,5);
		formData.top = new FormAttachment(label_totalNumSoldData,10);
		formData.right = new FormAttachment(100,-35);
		label_prepaidValueData.setLayoutData(formData);

		Label label_discountValue = new Label(groupLeft,SWT.RIGHT);
		label_discountValue.setText("整单折让:");
		label_discountValue.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(label_prepaidValue,10);
		label_discountValue.setLayoutData(formData);

		final Label label_discountValueData;
		label_discountValueData = new Label(groupLeft,SWT.RIGHT);
		label_discountValueData.setText("0.00");
		label_discountValueData.setFont(SWTResourceManager.getFont("", 16, SWT.BOLD));
		formData = new FormData();
		formData.left = new FormAttachment(label_discountValue,5);
		formData.right = new FormAttachment(100,-35);
		formData.top = new FormAttachment(label_prepaidValueData,10);
		label_discountValueData.setLayoutData(formData);

		//===========================================================================================//

		Group groupRight = new Group(container, SWT.NULL);
		groupRight.setText("付款信息");
		formData = new FormData();
		formData.left = new FormAttachment(groupLeft,15);
		formData.top = new FormAttachment(productItemtable,25);
		formData.bottom = new FormAttachment(100,-125);
		formData.right = new FormAttachment(100,-15);
		groupRight.setLayoutData(formData);
		groupRight.setLayout(new FormLayout());

		final Label label_totalPayables = new Label(groupRight,SWT.RIGHT);
		label_totalPayables.setText("应付:");
		label_totalPayables.setFont(SWTResourceManager.getFont("", 24, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(0,20);
		formData.top = new FormAttachment(0,35);
		label_totalPayables.setLayoutData(formData);

		final Label label_totalPayablesData = new Label(groupRight,SWT.RIGHT);
		label_totalPayablesData.setText("0.00");
		label_totalPayablesData.setFont(SWTResourceManager.getFont("", 24, SWT.BOLD));
		formData = new FormData();
		formData.left = new FormAttachment(label_totalPayables,25);
		formData.right = new FormAttachment(100,-25);
		formData.top = new FormAttachment(0,35);
		label_totalPayablesData.setLayoutData(formData);
		//-----------------------Line 4 end-----------------------------------------

		//-----------------------Line 5 start-----------------------------------------
		Label label_productItemId = new Label(container,SWT.RIGHT);
		label_productItemId.setText("产品编号：");
		label_productItemId.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(0,15);
		formData.top = new FormAttachment(groupLeft,15);
		label_productItemId.setLayoutData(formData);

		final Button button_query = new Button(container,SWT.NONE);
		button_query.setText("...");
		button_query.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.right = new FormAttachment(groupRight,-15);
		formData.top = new FormAttachment(groupLeft,15);
		button_query.setLayoutData(formData);

		final Text text_productItemId = new Text(container,SWT.BORDER);
		formData = new FormData();
		text_productItemId.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData.left = new FormAttachment(label_productItemId,5);
		formData.top = new FormAttachment(groupLeft,15);
		formData.right = new FormAttachment(button_query,-20);
		text_productItemId.setLayoutData(formData);

		button_query.addSelectionListener(new SelectionAdapter(){
			@Override
			public void widgetSelected(SelectionEvent e) {

				ProductSelector2 productSelector = new ProductSelector2(parent.getShell(),true);
				productSelector.open();
				ProductItemVO selectedProduct = productSelector.getSelectedProduct();
				if(selectedProduct != null){
					text_productItemId.setText(selectedProduct.getSn());
				}
				text_productItemId.forceFocus();
			}
		});

		Label label_seller = new Label(container,SWT.RIGHT);
		label_seller.setText("销售员:");
		label_seller.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.left = new FormAttachment(button_query,15);
		formData.top = new FormAttachment(groupLeft,15);
		label_seller.setLayoutData(formData);

		final Button button_bill = new Button(container,SWT.NONE);
		button_bill.setText("结单");
		button_bill.setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		formData = new FormData();
		formData.right = new FormAttachment(100,-15);
		formData.top = new FormAttachment(groupLeft,15);
		button_bill.setLayoutData(formData);

		final ComboViewer comboViewer_staff = new ComboViewer(container,SWT.BORDER|SWT.READ_ONLY);
		setProviderForStaff(comboViewer_staff);
		comboViewer_staff.setComparer(new IElementComparer(){

			@Override
			public boolean equals(Object a, Object b) {
				Integer a_id = ((StaffInfoTO)a).getId();
				Integer b_id = ((StaffInfoTO)b).getId();

				if(a_id == null || b_id == null){
					return false;
				}

				if(a_id.equals(b_id)){
					return true;
				}

				return false;
			}

			@Override
			public int hashCode(Object element) {
				return element.hashCode();
			}

		});
		comboViewer_staff.getCombo().setFont(SWTResourceManager.getFont("", 16, SWT.NONE));
		List<StaffInfoTO> ls = new ArrayList<StaffInfoTO>();
		if(staffOwner != null){
			String agentId = staffOwner.getAgentId();
			ls = cs.getListOfStaffUnderSameAgent(agentId);
			comboViewer_staff.setInput(ls);
			//set to be login user as default.
//			comboViewer_staff.setSelection(new StructuredSelection(loginUser));
		}

		formData = new FormData();
		formData.left = new FormAttachment(label_seller,5);
		formData.top = new FormAttachment(groupLeft,15);
		formData.right = new FormAttachment(button_bill,-10);
		comboViewer_staff.getCombo().setLayoutData(formData);

		button_bill.addSelectionListener(new SelectionAdapter(){
			@Override
			public void widgetSelected(SelectionEvent e){
				closeBill(l_Retail,
						parent,
						comboViewer_staff,
						label_totalPayablesData,
						label_totalNumSoldData,
						label_prepaidValueData,
						label_discountValueData,
					    businessDate,
						receipt_ProdItem,
						wl,
						false);
			}
		});
		//-----------------------Line 5 end-----------------------------------------

		text_productItemId.addKeyListener(new KeyListener(){
			@Override
			public void keyPressed(KeyEvent e) {

			}
			@Override
			public void keyReleased(KeyEvent e) {
				if(e.keyCode == 13){
					addBillItem(text_productItemId,
							parent,
							l_Retail,
							wl,
							label_totalPayablesData,
							receipt_ProdItem,
							label_totalNumSoldData,
							label_prepaidValueData,
							label_discountValueData);
				}
			}
		});


		final MenuManager menuManager = new MenuManager();
		final Menu menu = menuManager.createContextMenu(productItemtable);

		Action suspendAction = new Action("挂起当前交易  F6") {
            @Override
            public void run() {
				if(l_Retail == null || l_Retail.size() == 0){
					MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "还没有选择产品！");
				}else{
					final StaffInfoTO selectStaff = (StaffInfoTO)((StructuredSelection)comboViewer_staff.getSelection()).getFirstElement();
					if(selectStaff == null || selectStaff.getId()==null){
						MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "还没有选择销售员！");
					}else{
						shopReceiptTO = assemShopReceiptTO(CODE_PROGRESS_HOLD, businessDate,receipt_ProdItem,selectStaff,l_Retail,null);
						try{
							rs.insertOrUpdateRetailRecord(shopReceiptTO);
							label_totalPayablesData.setText("0.00");
							shopReceiptTO = null;
							wl.clear();
							receipt_ProdItem.clear();

							label_discountValueData.setText("0.00");
							label_prepaidValueData.setText("0.00");
							label_totalNumSoldData.setText("0");

							MessageDialog.openInformation(parent.getShell(), "保存", "挂起成功！");

						}catch(RetailServiceException e1){
							MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, e1.getMessage());
						}
					}
				}
            }
        };

        activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.suspend", new ActionHandler(suspendAction)));
		menuManager.add(suspendAction);


		Action resumeSuspendAction = new Action("恢复挂起交易  F7") {
			@Override
            public void run(){
				if(staffOwner == null){
					MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "请检查登录用户所属门店！");
					return;
				}
				RetailHoldSelectDialog retailHoldSelectDialog = new RetailHoldSelectDialog(parent.getShell(),staffOwner.getAgentId());
				retailHoldSelectDialog.open();

				shopReceiptTO = retailHoldSelectDialog.getShopReceiptTO();

				if(shopReceiptTO!=null && shopReceiptTO.getId()!=null){
					wl.clear();
					receipt_ProdItem.clear();

					Set<ShopReceiptPdtItemTO> s = shopReceiptTO.getPdtItemSoldList();
					for(Iterator<ShopReceiptPdtItemTO> it = s.iterator(); it.hasNext();){
						ShopReceiptPdtItemTO t = (ShopReceiptPdtItemTO)it.next();
						RetailVO retailVO = new RetailVO(t);
						wl.add(retailVO);
					}
					receipt_ProdItem.addAll(s);

					formatPaidValue(l_Retail,label_totalPayablesData,label_totalNumSoldData,label_prepaidValueData,label_discountValueData);

					comboViewer_staff.setSelection(new StructuredSelection(shopReceiptTO.getSeller()));
				}
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.resumeSuspend", new ActionHandler(resumeSuspendAction)));
		menuManager.add(resumeSuspendAction);

		Action cancelSuspendAction = new Action("舍弃挂起交易  Ctrl+F7") {
			@Override
            public void run(){

				if(staffOwner == null){
					MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "请检查登录用户所属门店！");
					return;
				}

				if(shopReceiptTO!=null && shopReceiptTO.getId()!=null && shopReceiptTO.getId() != 0){
					boolean confirmed = MessageDialog.openConfirm(parent.getShell(), "确认", "要舍弃当前交易吗？");
					if( ! confirmed){
						return;
					}
					rs.cancelHeldReceipt(shopReceiptTO);
					wl.clear();
					receipt_ProdItem.clear();
					formatPaidValue(l_Retail,label_totalPayablesData,label_totalNumSoldData,label_prepaidValueData,label_discountValueData);
				}else{
					MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "当前没有挂起交易，无法舍弃。");
				}
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.cancelSuspend", new ActionHandler(cancelSuspendAction)));
		menuManager.add(cancelSuspendAction);

		menuManager.add(new ActionSetSeparator("",""));

		final Action clearAction = new Action("删除当前明细  F3") {
			public void run(){
				if(selectRetailVO != null){
					reduceBillItem(wl,receipt_ProdItem,l_Retail,label_totalPayablesData,label_totalNumSoldData,label_prepaidValueData,label_discountValueData);
					setEnabled(false);
				}
			}
		};
		clearAction.setId("retail.item.clear");
		clearAction.setEnabled(false);

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.clear", new ActionHandler(clearAction)));
		menuManager.add(clearAction);

		Action clearAllAction = new Action("清除所有信息  F4") {
			@Override
			public void run(){
				if(l_Retail == null || l_Retail.size() == 0){
					MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "没有选项需要清除！");
				}else{
					label_totalPayablesData.setText("0.00");
					wl.clear();
					receipt_ProdItem.clear();

					label_discountValueData.setText("0.00");
					label_prepaidValueData.setText("0.00");
					label_totalNumSoldData.setText("0");
				}
				clearAction.setEnabled(false);
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.clearAll", new ActionHandler(clearAllAction)));
		menuManager.add(clearAllAction);

		menuManager.add(new ActionSetSeparator("",""));

		Action payAction = new Action("结账收银  F8") {
			@Override
			public void run(){
				closeBill(l_Retail,
						parent,
						comboViewer_staff,
						label_totalPayablesData,
						label_totalNumSoldData,
						label_prepaidValueData,
						label_discountValueData,
					    businessDate,
						receipt_ProdItem,
						wl,
						false);
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.payBill", new ActionHandler(payAction)));

		menuManager.add(payAction);

		Action payAssembleAction = new Action("组合收银  Shift+F8") {
			@Override
			public void run(){
				closeBill(l_Retail,
						parent,
						comboViewer_staff,
						label_totalPayablesData,
						label_totalNumSoldData,
						label_prepaidValueData,
						label_discountValueData,
					    businessDate,
						receipt_ProdItem,
						wl,
						true);
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.payBillAssemble", new ActionHandler(payAssembleAction)));
		menuManager.add(payAssembleAction);

		menuManager.add(new ActionSetSeparator("",""));

		Action returnAction = new Action("退货  F9", IAction.AS_CHECK_BOX) {
			@Override
			public void run(){
				toggleReject();
				setChecked(isRejected);
			}
		};

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.toggleReturn", new ActionHandler(returnAction)));
		menuManager.add(returnAction);

		Action printAction = new Action("打印  F2", IAction.AS_CHECK_BOX) {
			@Override
			public void run(){
				togglePrintReceipt();
				setChecked(printReceipt);
			}
		};
		//default selected.
		printAction.setChecked(true);

		activatedHandlers.add(handlerService.activateHandler("com.balance.anole.client.retail.view.RetailView.togglePrint", new ActionHandler(printAction)));
		menuManager.add(printAction);



		productItemtable.setMenu(menu);

		tableViewer.getTable().addSelectionListener(new SelectionListener(){

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				((ActionContributionItem)menuManager.find("retail.item.clear")).getAction().setEnabled(true);
			}

			@Override
			public void widgetSelected(SelectionEvent e) {
				((ActionContributionItem)menuManager.find("retail.item.clear")).getAction().setEnabled(true);
			}

		});
		tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				StructuredSelection selection = (StructuredSelection)event.getSelection();
				Object element = selection.getFirstElement();
				if(element != null){
					selectRetailVO = (RetailVO)element;
				}
			}
		});

		text_productItemId.forceFocus();

	}

	@Override
	public void setFocus() {

	}

	private void toggleReject(){
		if( ! isRejected){
			isRejected = true;
			label_statusData.setText(label_statusData.getText().replace("[正常销售]", "[退货]"));
		}else{
			isRejected = false;
			label_statusData.setText(label_statusData.getText().replace("[退货]", "[正常销售]"));
		}
		controlStatusLabelStyle();
	}

	private void controlStatusLabelStyle(){
		if(isRejected || !printReceipt){
			label_statusData.setForeground(SWTResourceManager.getColor(255, 0, 0));
		}else{
			label_statusData.setForeground(SWTResourceManager.getColor(0, 0, 0));
		}
	}

	private void togglePrintReceipt(){
		if( ! printReceipt){
			this.printReceipt = true;
			label_statusData.setText(label_statusData.getText().replace(" [不打印]", " [打印]"));
		}else{
			this.printReceipt = false;
			label_statusData.setText(label_statusData.getText().replace(" [打印]", " [不打印]"));
		}
		controlStatusLabelStyle();
	}

	private void closeBill(List<RetailVO> l_Retail,
							Composite parent,
							ComboViewer comboViewer_staff,
							Label label_totalPayablesData,
							Label label_totalNumSoldData,
							Label label_prepaidValueData,
							Label label_discountValueData,
							BusinessDateTO businessDate,
							Set<ShopReceiptPdtItemTO> receipt_ProdItem,
							WritableList wl,
							boolean isAssClose){
		if(l_Retail == null || l_Retail.size() == 0){
			MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "还没有选择产品！");
		}else{
			final StaffInfoTO selectStaff = (StaffInfoTO)((StructuredSelection)comboViewer_staff.getSelection()).getFirstElement();
			if(selectStaff == null || selectStaff.getId()==null){
				MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "还没有选择销售员！");
				comboViewer_staff.getCombo().forceFocus();
			}else{
				String needPayStr = label_totalPayablesData.getText();

				Dialog retailCloseDialog;

				if(isAssClose){
					retailCloseDialog = new RetailAssemCloseDialog(parent.getShell(),needPayStr);
				}else{
					retailCloseDialog = new RetailCloseDialog(parent.getShell(),needPayStr);
				}

				int digReturn = retailCloseDialog.open();

				if(Window.OK == digReturn){
					Set<ShopPaymentTO> shopPaymentTOs;

					String paidValueStr = "";
					String changeValueStr = "";

					if(isAssClose){
						RetailAssemCloseDialog dialog = (RetailAssemCloseDialog)retailCloseDialog;
						shopPaymentTOs = dialog.getShopPaymentTOs();
						paidValueStr = dialog.getTotalPaidValue();
						changeValueStr = dialog.getTotalChangeValue();
					}else{
						RetailCloseDialog dialog = (RetailCloseDialog)retailCloseDialog;
						shopPaymentTOs = dialog.getShopPaymentTOs();
						paidValueStr = dialog.getTotalPaidValue();
						changeValueStr = dialog.getTotalChangeValue();
					}


					try{
						shopReceiptTO = assemShopReceiptTO(CODE_PROGRESS_FINAL, businessDate,receipt_ProdItem,selectStaff,l_Retail,shopPaymentTOs);

						RetailReceiptPrintVO printVO = null;
						if(printReceipt){
							printVO = new RetailReceiptPrintVO();
							printVO.setCashier(shopReceiptTO.getCashier().getStaffId());
							printVO.setChange(changeValueStr);
							printVO.setDate(FormatHelper.formatDate(new Date(), "yyyy-MM-dd"));
							printVO.setNeedPay(needPayStr);
							printVO.setPaid(paidValueStr);
							printVO.setSeller(shopReceiptTO.getSeller().getStaffId());

							for(RetailVO prod : l_Retail){
								ProductItemDetail productItem = new ProductItemDetail();
								productItem.setAmount(NumberUtil.formatMoney(prod.getAmountAfterDiscount()));
								productItem.setDiscount(NumberUtil.formatMoney(prod.getDiscount()));
								productItem.setNum(String.valueOf(prod.getNumOfPdtItem().intValue()));
								productItem.setProdSn(prod.getPdtItem().getSn());
								ProductPriceTO ppt = prod.getPdtItem().getProductTO().getPriceByType(new CodeLookTO(Constants.CODE_TYPE_PRODUCT_PRICE_TYPE, "S"));
								BigDecimal price = ppt == null ? BigDecimal.ZERO : ppt.getPrice();
								productItem.setPrice(NumberUtil.formatMoney(price));
								printVO.addProductItem(productItem);
							}

							for(ShopPaymentTO payment: shopPaymentTOs){
								PaymentItemDetail paymentItem = new PaymentItemDetail();
								paymentItem.setPaymentDesc(BizCodesService.getInstance().getCodeDesc(payment.getPaymentMode().getCodeTypeId(), payment.getPaymentMode().getCodeId(), true));
								paymentItem.setPaidValue((new BigDecimal(needPayStr).signum() < 0 ? "-" : "") + NumberUtil.formatMoney(payment.getPaidValue()));
								printVO.addPaymentItem(paymentItem);
							}

						}

						rs.payBill(printVO, shopReceiptTO, needPayStr, paidValueStr,changeValueStr);
//						rs.insertOrUpdateRetailRecord(shopReceiptTO);
						label_totalPayablesData.setText("0.00");

						label_discountValueData.setText("0.00");
						label_prepaidValueData.setText("0.00");
						label_totalNumSoldData.setText("0");

						wl.clear();
						receipt_ProdItem.clear();

						MessageDialog.openInformation(parent.getShell(), "保存", "保存成功！");

						//set back to normal status.
						if(isRejected){
							toggleReject();
						}
						if( ! printReceipt){
							togglePrintReceipt();
						}
					}catch(Exception e1){
						MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, e1.getMessage());
					}
				}
			}
		}
	}

	private void setProviderForStaff(ComboViewer viewer){
		viewer.setLabelProvider(new StaffComboLabelProvider());
		viewer.setContentProvider(new ArrayContentProvider());
	}

	private ShopReceiptTO assemShopReceiptTO(String flagProgress,
										BusinessDateTO businessDate,
										Set<ShopReceiptPdtItemTO> receipt_ProdItem,
										StaffInfoTO selectStaff,
										List<RetailVO> l_Retail,
										Set<ShopPaymentTO> shopPaymentTOs){
		if (shopReceiptTO == null){
			shopReceiptTO = new ShopReceiptTO();
		}

		shopReceiptTO.setReceiptDate(DateUtil.getSystemCurrentDate());
		shopReceiptTO.setBusinessDate(businessDate);
		shopReceiptTO.setLineNum("1"); //TODO:
		Set<ShopReceiptPdtItemTO> pdtItems = shopReceiptTO.getPdtItemSoldList();
		if(pdtItems != null){
			pdtItems.clear();
		}else{
			pdtItems = new HashSet<ShopReceiptPdtItemTO>();
			shopReceiptTO.setPdtItemSoldList(pdtItems);
		}
		pdtItems.addAll(receipt_ProdItem);
		shopReceiptTO.setSeller(selectStaff);
		shopReceiptTO.setShop(cs.getShop(SessionManager.getInstance().getLoginUser().getStaffInfo().getStaffOwner()));
		shopReceiptTO.setCashier(SessionManager.getInstance().getLoginUser().getStaffInfo());
		BigDecimal needPay = getTotalPayablesValue(l_Retail);
		shopReceiptTO.setTotalSoldValue(needPay);

		Set<ShopPaymentTO> shopPaymentTOsAfterCalculate = PaymentHelper.getShopPaymentsAfterCalculate(needPay.signum() < 0, needPay, shopPaymentTOs);
		shopReceiptTO.setPaymentList(shopPaymentTOsAfterCalculate);
		shopReceiptTO.setTotalPaidValue(getTotalPaidValue(shopPaymentTOsAfterCalculate));
		shopReceiptTO.setTotalNumOfPdtItem(new BigDecimal(getTotalNumOfPdtItem(l_Retail)));
//		shopReceiptTO.setProgress(cs.getCodeLookTOByCodeTypeAndCodeId(CODE_PROCESS, flagProgress));
		shopReceiptTO.setProgress(new CodeLookTO(CODE_PROCESS, flagProgress));
		shopReceiptTO.setCreateBy(SessionManager.getInstance().getLoginUser().getStaffInfo());
		shopReceiptTO.setCreateDt(DateUtil.getSystemCurrentDate());

		return shopReceiptTO;
	}

	private void reduceBillItem(WritableList wl,
								Set<ShopReceiptPdtItemTO> receipt_ProdItem,
								List<RetailVO> l_Retail,
								Label label_totalPayablesData,
								Label label_totalNumSoldData,
								Label label_prepaidValueData,
								Label label_discountValueData){

		if(receipt_ProdItem!=null){
			for(Iterator<ShopReceiptPdtItemTO> it = receipt_ProdItem.iterator(); it.hasNext();){
				ShopReceiptPdtItemTO t = (ShopReceiptPdtItemTO)it.next();

				if(t.getNumOfPdtItem().intValue() < 0){
					if(t.getPdtItem().getSn().equals(selectRetailVO.getPdtItem().getSn()) && selectRetailVO.isRejected()){
						it.remove();
					}
				}else{
					if(t.getPdtItem().getSn().equals(selectRetailVO.getPdtItem().getSn()) && !selectRetailVO.isRejected()){
						it.remove();
					}
				}
			}
		}

		wl.remove(selectRetailVO);
		formatPaidValue(l_Retail,label_totalPayablesData,label_totalNumSoldData,label_prepaidValueData,label_discountValueData);
	}

	private RetailVO checkExistRetailVO(List<RetailVO> l_Retail,ProductItemTO productItemTO){
		if(l_Retail != null){
			for(Iterator<RetailVO> it = l_Retail.iterator(); it.hasNext();){
				RetailVO t = (RetailVO)it.next();
				if(t.getPdtItem().getSn().equals(productItemTO.getSn())){
					if(isRejected && t.getNumOfPdtItem().intValue()<0){
						return t;
					}

					if(!isRejected && t.getNumOfPdtItem().intValue()>0){
						return t;
					}

				}
			}
		}
		return null;
	}

	private void addRetailVO(RetailVO retailVO,int num){
		retailVO.setNumOfPdtItem(retailVO.getNumOfPdtItem().add(new BigDecimal(num)));
	}

	private void addBillItem(Text text_goodsId,
								Composite parent,
								List<RetailVO> l_Retail,
								WritableList wl,
								Label label_totalPayablesData,
								Set<ShopReceiptPdtItemTO> receipt_ProdItem,
								Label label_totalNumSoldData,
								Label label_prepaidValueData,
								Label label_discountValueData) {
		final CommonService cs = ServicesCenter.getServicesCenter().getService(CommonService.class);

		if(text_goodsId!=null && text_goodsId.getText()!=null && !"".equals(text_goodsId.getText())){
			ProductItemTO productItemTO = cs.getPdtItemBySN(text_goodsId.getText());
			if(productItemTO == null){
				MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "编号[" + text_goodsId.getText() + "] 的产品不存在！");
			}else{
				RetailVO retailVO = checkExistRetailVO(l_Retail,productItemTO);

				if(retailVO != null){
					wl.remove(retailVO);
					if(isRejected){
						addRetailVO(retailVO,-1);
					}else{
						addRetailVO(retailVO,1);
					}
				}else{
					retailVO = new RetailVO(productItemTO);
					retailVO.setCreateBy(SessionManager.getInstance().getLoginUser().getStaffInfo());
					retailVO.setCreateDt(DateUtil.getSystemCurrentDate());

					if(isRejected){
						retailVO.setNumOfPdtItem(retailVO.getNumOfPdtItem().multiply(new BigDecimal(-1)));
					}
				}

				wl.add(retailVO);
				receipt_ProdItem.add(retailVO);

				formatPaidValue(l_Retail,label_totalPayablesData,label_totalNumSoldData,label_prepaidValueData,label_discountValueData);
				text_goodsId.setText("");
			}
		}else{
			MessageDialog.openError(parent.getShell(), Messages.DIALOG_INFO_ERROR, "请输入产品编号！");
		}

	}

	private void formatPaidValue(List<RetailVO> l_Retail,
								Label label_totalPayablesData,
								Label label_totalNumSoldData,
								Label label_prepaidValueData,
								Label label_discountValueData){

		label_totalNumSoldData.setText(getTotalNumOfPdtItem(l_Retail)+"");

		BigDecimal m = getTotalPayablesValue(l_Retail);
		label_totalPayablesData.setText(NumberUtil.formatMoney(m));

		BigDecimal m_p = getTotalPrepaidValue(l_Retail);
		label_prepaidValueData.setText(NumberUtil.formatMoney(m_p));

		BigDecimal m_d = m_p.subtract(m);
		label_discountValueData.setText(NumberUtil.formatMoney(m_d));
	}

	private BigDecimal getTotalPayablesValue(List<RetailVO> l_Retail){
		BigDecimal m = BigDecimal.ZERO;
		for(int i=0;i<l_Retail.size();i++){
			BigDecimal s_m = ((RetailVO)l_Retail.get(i)).getAmountAfterDiscount();
			m = m.add(s_m);
		}
		return m;
	}

	private BigDecimal getTotalPaidValue(Set<ShopPaymentTO> shopPaymentTOs){
		BigDecimal m = BigDecimal.ZERO;
		if(shopPaymentTOs != null){
			for (Iterator<ShopPaymentTO> iterator = shopPaymentTOs.iterator(); iterator.hasNext();) {
				ShopPaymentTO shopPaymentTO = (ShopPaymentTO) iterator.next();
				m = m.add(shopPaymentTO.getPaidValue());
			}
		}
		return m;
	}

	private BigDecimal getTotalPrepaidValue(List<RetailVO> l_Retail){
		BigDecimal m = BigDecimal.ZERO;
		for(int i=0;i<l_Retail.size();i++){
			RetailVO vo = (RetailVO)l_Retail.get(i);
			ProductPriceTO ppt = vo.getPdtItem().getProductTO().getPriceByType(new CodeLookTO(Constants.CODE_TYPE_PRODUCT_PRICE_TYPE, "S"));
			BigDecimal price = ppt == null ? BigDecimal.ZERO : ppt.getPrice();
			BigDecimal num = vo.getNumOfPdtItem();
			BigDecimal s_m = price.multiply(num);
			m = m.add(s_m);
		}
		return m;
	}

	private int getTotalNumOfPdtItem(List<RetailVO> l_Retail){
		BigDecimal m = BigDecimal.ZERO;
		for(int i=0;i<l_Retail.size();i++){
			RetailVO vo = (RetailVO)l_Retail.get(i);
			BigDecimal num = vo.getNumOfPdtItem();
			m = m.add(num);
		}
		return m.intValue();
	}

	@Override
	public void dispose() {
		handlerService.deactivateHandlers(activatedHandlers);
		super.dispose();
	}

}
